import './style.scss'
import { createContext, ReactNode, useContext, useEffect, useState } from 'react';
import { LoadingOutlined } from '@ant-design/icons';

type MessageType = 'loading' | 'text';

type MessagePayload = {
  id: string
  type: MessageType
  content: ReactNode
  duration: number
  closeTimer?: ReturnType<typeof setTimeout>
}


type MessageContextOptions = {
  activeValue: boolean
  typeValue: MessageType
  contentValue: ReactNode
  switchAnimateClass: string,
  setSwitchAnimateClass(value: string): void,
  showMessage(options: Partial<MessagePayload>): string
  closeMessage(id?: string): void
}

let autoMessageId = 0;

const messageQueue: MessagePayload[] = [];

const MessageContext = createContext<MessageContextOptions>({
  activeValue: false,
  typeValue: 'text',
  contentValue: null,
  switchAnimateClass: '',
  setSwitchAnimateClass: function(){},
  showMessage: function(){ return '' },
  closeMessage: function(){},
})

export const useMessage = () => useContext(MessageContext)

export const MessageComponent = () => {
  const { activeValue, typeValue, contentValue, switchAnimateClass, setSwitchAnimateClass } = useMessage()
  
  const onContentTransitionEnd = () => {
    switch(switchAnimateClass){
      case 'leave': {
        setSwitchAnimateClass('leave-to-enter')
        break;
      }
      
      case 'enter': {
        setSwitchAnimateClass('')
        break;
      }
      default: break;
    }
  }

  const onContentAnimationEnd = () => {
    setSwitchAnimateClass('')
  }

  useEffect(() => {
    requestAnimationFrame(() => {
      switch(switchAnimateClass){
        case 'leave leave-active': {
          setSwitchAnimateClass('leave')
          break;
        }
        
        case 'enter enter-active': {
          setSwitchAnimateClass('enter')
          break;
        }
  
        case 'leave-to-enter': {
          setSwitchAnimateClass('enter enter-active')
          break;
        }
        default: break;
      }
    })
  }, [switchAnimateClass])

  return <>
    <div className={`params-message ${activeValue ? 'active' : ''}`}>
      {
        typeValue == 'loading' && <>
          <div className="params-message-loading">
            <LoadingOutlined />
          </div>
        </>
      }
      <div 
        className={`params-message-content ${switchAnimateClass}`} 
        onTransitionEnd={onContentTransitionEnd}
        onAnimationEnd={onContentAnimationEnd}
      >{ contentValue }</div>
    </div>
  </>
}

export const MessageProvider = ({ children }: { children: ReactNode }) => {
  const { activeValue, typeValue, contentValue } = useMessage()
  const [active, setActive] = useState(activeValue);
  const [type, setType] = useState<MessageType>(typeValue);
  const [content, setContent] = useState<ReactNode>(contentValue);
  const [switchAnimateClass, setSwitchAnimateClass] = useState('');


  const showMessage: MessageContextOptions['showMessage'] = (options) => {
    const messageIndex = messageQueue.findIndex(message => message.id === options.id);

    const action = (newOptions: MessagePayload) => {
      if(newOptions.closeTimer) clearTimeout(newOptions.closeTimer)
      if(newOptions.duration > 0){  // 延迟关闭
        newOptions.closeTimer = setTimeout(() => {
          closeMessage(newOptions.id)
        }, newOptions.duration * 1000)
      }
  
      setType(newOptions.type)
      setContent(newOptions.content)
      setActive(true)

      if(messageIndex > -1) {
        messageQueue.splice(messageIndex, 1, newOptions)
        setSwitchAnimateClass('fastflicker')
      }
      else {
        messageQueue.push(newOptions)
        if(messageQueue.length > 1) setSwitchAnimateClass('leave leave-active')
      }

      return newOptions
    }

    return action({
      id: options.id !== undefined ? options.id : `message-${++autoMessageId}`,
      type: options.type !== undefined ? options.type : 'text',
      content: options.content !== undefined ? options.content : '',
      duration: typeof options.duration == 'number' ? options.duration : (options.type === 'loading' ? 0 : 3),
      closeTimer: options.closeTimer
    }).id
  }

  const closeMessage: MessageContextOptions['closeMessage'] = (id) => {  // 无id时，关闭当前消息
    const messageIndex = id !== undefined ? messageQueue.findIndex(message => message.id === id) : messageQueue.length-1;
    if(messageIndex > -1) messageQueue.splice(messageIndex, 1)

    if(messageQueue.length == 0) setActive(false)
    else {
      const lastMessage = messageQueue[messageQueue.length - 1];
      setType(lastMessage.type)
      setContent(lastMessage.content)
      if(messageQueue.length > 1) setSwitchAnimateClass('leave leave-active')
    }
  }


  return <>
    <MessageContext.Provider value={{
      activeValue: active,
      typeValue: type,
      contentValue: content,
      switchAnimateClass,
      setSwitchAnimateClass,
      showMessage,
      closeMessage,
    }}>{ children }</MessageContext.Provider>
  </>    
}